{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Coin toss quantum circuit\n",
    "In this exercise we create a quantum circuit that simulates the probabilistic nature of a single qubit in superposition. The one qubit circuit initializes the qubit in the ground state $|0\\rangle$ and then uses a Hadamard gate to put the qubit in superposition $|\\psi\\rangle = \\left(|0\\rangle+|1\\rangle\\right)/\\sqrt{2}.$  \n",
    "Measuring the qubit causes it to collapse into one of the states $|0\\rangle$ or $|1\\rangle$ with a 50% probability, i.e. a coin toss.   \n",
    "In this exercise we introduce the Hadamard gate, which puts a qubit in superposition.\n",
    "```\n",
    "        ┌───┐  \n",
    "q_0: |0>┤ H ├  \n",
    "        └───┘  \n",
    "```\n",
    "\n",
    "We also introduce the X gate that flips the qubit from $|0\\rangle$ to $|1\\rangle$ and vice versa.\n",
    "```\n",
    "        ┌───┐\n",
    "q_0: |0>┤ X ├\n",
    "        └───┘\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Import the required libraries."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "from qiskit import QuantumCircuit, execute, Aer\n",
    "\n",
    "# Import Blochsphere visualization\n",
    "from qiskit.visualization import plot_bloch_multivector, plot_histogram"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "As we will be using the Bloch sphere visualization (`plot_bloch_multivector`) a bit, here's a quick function that calculates the state vector ($|\\psi\\rangle$) for the circuit to let you display the Bloch vector for any given state.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "def get_psi(circuit): \n",
    "    global psi\n",
    "    backend = Aer.get_backend('statevector_simulator') \n",
    "    psi = execute(circuit, backend).result().get_statevector(circuit)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Create an empty quantum circuit. We start out with the qubit in the $|0\\rangle$ state."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "qc = QuantumCircuit(1,1)\n",
    "\n",
    "# Print out the circuit\n",
    "print(qc)\n",
    "\n",
    "# Display the Bloch sphere\n",
    "get_psi(qc)\n",
    "plot_bloch_multivector(psi)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Add a Hadamard (super position) gate to the quantum circuit. This puts the qubit in a superposition: $|\\psi\\rangle = \\left(|0\\rangle+|1\\rangle\\right)/\\sqrt{2}.$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "qc.h(0)\n",
    "\n",
    "# Print out the circuit\n",
    "print(qc)\n",
    "\n",
    "# Display the Bloch sphere\n",
    "get_psi(qc)\n",
    "plot_bloch_multivector(psi)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Finally, add a measurement gate to complete the circuit."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "# Add measure gate\n",
    "qc.measure(0,0)\n",
    "print(qc)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Set the backend to a local simulator."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "backend = Aer.get_backend('qasm_simulator')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Create a quantum job that runs just one shot to simulate a coin toss. Then run the job and display the result; either 0 for up (base) or 1 for down (excited). Display the result as a histogram."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "job = execute(qc, backend, shots=1)\n",
    "counts  = job.result().get_counts()\n",
    "print(counts)\n",
    "plot_histogram(counts)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Now, lets run a thousand coin tosses in a row and see what we get."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "job = execute(qc, backend, shots=1000)\n",
    "counts  = job.result().get_counts()\n",
    "print(counts)\n",
    "plot_histogram(counts)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "In the histogram we see that we get 0 and 1 with ~50% probability. Which is what we expect from tossing some coins."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "We can also do our coin flip with the qubit starting in the $|1\\rangle$ state by first flipping the qubit by using the X gate. The Hadamard gate still flips the qubit to the equator, but now on the -X side."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "qc2 = QuantumCircuit(1,1)\n",
    "qc2.x(0)\n",
    "qc2.h(0)\n",
    "print(qc2)\n",
    "# Display the Bloch sphere\n",
    "get_psi(qc2)\n",
    "plot_bloch_multivector(psi)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Add the measure gate and run the circuit 1,000 times."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "qc2.measure(0,0)\n",
    "\n",
    "job2 = execute(qc2, backend, shots=1000)\n",
    "counts2  = job2.result().get_counts()\n",
    "print(counts2)\n",
    "plot_histogram(counts2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "As you can see, there is no real difference in the outcome. "
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
